import React, { useEffect, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { NetworkStatus } from '@apollo/client';
import { ErrorMessage } from '@hookform/error-message';
import {
  AutoComplete,
  Box,
  Datepicker,
  FormStatusMessage,
  Icon,
  Input,
  MainButton,
  makeToast,
  Modal,
  ModalHeader,
  Text,
} from '@nova-hf/ui';
import { OptionsType } from '@nova-hf/ui/umd/ts/src/form-elements/react-select-components/ReactSelectWrapper';
import { ModalProps } from '@nova-hf/ui/umd/ts/src/modal/Modal';
import { ErrorBanner } from 'beta/components/error/ErrorBanner';
import Authentication from 'beta/store/authentication';
import UI from 'beta/store/ui';
import { betaRoutingMaster, formatDate } from 'beta/utils/helpers';
import { useTranslation } from 'beta/utils/i18n';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import {
  ReasonsForCancellingContractOrder_CfContent,
  useCustomerNationalIdQuery,
  useReasonsForCancelQuery,
  useTerminateServiceMutation,
} from 'typings/graphql';

import { SettingsButtons } from '../components/SettingsButtons';
import { StillingarLoader } from '../components/StillingarLoader';

type ConfirmDeleteModalProps = {
  whenToApplyDate: Date;
  isLoading?: boolean;
  onClose?: () => void;
  onDelete?: () => void;
} & Pick<ModalProps, 'isVisible' | 'onVisibilityChange'>;

export const ConfirmDeleteModal = ({
  isVisible,
  whenToApplyDate,
  isLoading,
  onClose,
  onDelete,
  onVisibilityChange,
}: ConfirmDeleteModalProps) => {
  const { t } = useTranslation('stillingar');

  const formattedWhenToApplyDate = formatDate(whenToApplyDate, 'dd.MM.yyyy');
  return (
    <Modal
      ariaLabel="Modal to confirm delete action"
      isVisible={isVisible}
      onVisibilityChange={onVisibilityChange}
    >
      <Box display="flex" flexDirection="column">
        <ModalHeader
          title={t('confirmDeleteModal.cancelContract.header')}
          eyebrow={t('confirmDeleteModal.cancelContract.eyebrow')}
          color="warning"
          icon="trash"
        />
        <Box marginY={5} flexGrow={1} display="flex" alignItems="center">
          <Text variant="pMediumRegular">
            {t('stillingar:confirmDeleteModal.cancelContract.serviceDescription', {
              whenToApplyDate: formattedWhenToApplyDate,
            })}
          </Text>
        </Box>
        <Box display="flex" flexDirection={['column', 'row', 'row']} gap={4}>
          <MainButton
            text={t('confirmDeleteModal.cancelButton')}
            onClick={onClose}
            colorScheme="white"
            dottedShadow="none"
            isDisabled={isLoading}
          />
          <MainButton
            text={t('confirmDeleteModal.cancelContract.cancelButton')}
            onClick={onDelete}
            colorScheme="warning"
            dottedShadow="none"
            isLoading={isLoading}
          />
        </Box>
      </Box>
    </Modal>
  );
};

type CancelContractForm = {
  id: string;
  whenToApplyDate: Date;
  moveServiceTo: string;
  reason: string;
  reasonDescription: string;
};

type CancelContractContainerProps = {
  ui?: UI;
  isTengir?: boolean;
  authentication?: Authentication;
};

const CancelContractContainer = ({
  ui,
  isTengir,
  authentication,
}: CancelContractContainerProps) => {
  const { t } = useTranslation(['stillingar', 'errors']);
  const router = useRouter();
  const isStaff = authentication?.isStaff;
  const customerId = router.query.customerId ?? '';
  const serviceId = router.query.serviceId ?? '';
  const [showConfirmationModal, setShowConfirmationModal] = useState(false);
  const [autoCompleteReasonOptions, setAutoCompleteReasonOptions] = useState<OptionsType[]>();

  const { control, watch, setValue, handleSubmit, formState, trigger, reset } =
    useForm<CancelContractForm>({
      defaultValues: {
        id: '',
        whenToApplyDate: new Date(),
        reason: '',
        reasonDescription: '',
      },
      mode: 'onChange',
      delayError: 500,
    });

  const watchAllFields = watch();

  const { data: customerData } = useCustomerNationalIdQuery({
    variables: { input: { id: customerId.toString() } },
  });

  const customerRouting = (customerId: string) => {
    betaRoutingMaster(
      `/beta/${customerId}/thjonustur/${serviceId}`,
      router,
      customerData?.customer?.nationalId ?? '',
      '/beta/:customerId/thjonustur',
    );
  };
  const [terminateService] = useTerminateServiceMutation({
    onCompleted: (data) => {
      if (data) {
        makeToast.success(
          t('stillingar:cancelContract.successTitle'),
          t('stillingar:cancelContract.successDescription'),
        );
        setShowConfirmationModal(false);
        customerRouting(customerId.toString());
      }
    },
    onError: (error) => {
      if (error instanceof Error) {
        setShowConfirmationModal(false);

        if (error.message.includes('An unprocessed termination for this service')) {
          makeToast.danger(
            t('stillingar:cancelContract.errorTitle'),
            t('stillingar:cancelContract.errorBadInputDescription'),
          );
        } else {
          makeToast.danger(
            t('stillingar:cancelContract.errorTitle'),
            t('stillingar:cancelContract.errorDescription'),
          );
        }
      }
    },
  });

  const { data, loading, error, refetch, networkStatus } = useReasonsForCancelQuery({
    variables: {
      order: ReasonsForCancellingContractOrder_CfContent.OrderAsc,
    },
  });
  const cancellingReasonItems = data?.reasonsForCancellingContractCollection?.items ?? [];
  const autoCompleteMoveServiceToOptions = cancellingReasonItems?.map((select) => {
    return {
      value: select?.id || '',
      label: select?.reason || '',
    };
  });

  useEffect(() => {
    setValue('id', serviceId.toString());
  }, []);

  useEffect(() => {
    if (cancellingReasonItems?.length) {
      const filterContentfulReason = cancellingReasonItems.filter(
        (cancellingReasonItem) => cancellingReasonItem?.reason === watchAllFields.moveServiceTo,
      );

      const reasonOptions = filterContentfulReason[0]?.optionsCollection?.items.map((item) => {
        return { value: item?.title || '', label: item?.title || '' };
      });
      setAutoCompleteReasonOptions(reasonOptions);
    }
  }, [watchAllFields.moveServiceTo]);

  useEffect(() => {
    trigger('reasonDescription');
  }, [watchAllFields.reason, trigger]);

  if (error || loading) {
    return (
      <ErrorBanner
        eyebrowTexts={[t('errors:cancelContract.eyebrows.1')]}
        titles={[
          t('errors:cancelContract.titles.1'),
          t('errors:cancelContract.titles.2'),
          t('errors:cancelContract.titles.3'),
        ]}
        descriptions={[t('errors:cancelContract.descriptions.1')]}
        icon="zap"
        color="attention"
        showLoading={loading || networkStatus === NetworkStatus.refetch}
        refetchButton={{
          text: t('errors:buttons.reload'),
          icon: 'refresh',
          onClick: () => refetch(),
        }}
        loadingComponent={<StillingarLoader />}
      />
    );
  }

  const onSubmit = (cancelContractForm: CancelContractForm) => {
    if (cancelContractForm.id && cancelContractForm.whenToApplyDate && formState.isValid)
      setShowConfirmationModal(true);
  };

  const handleCancelContract = async () => {
    await terminateService({
      variables: {
        input: {
          terminateAt: watchAllFields.whenToApplyDate,
          id: watchAllFields.id,
          reason: `${watchAllFields.moveServiceTo} - ${watchAllFields.reason}`,
          message: `${watchAllFields.reasonDescription}`,
        },
      },
    });
  };

  const moveServiceRule = () => ({
    required: t('stillingar:cancelContract.missingMoveService') ?? '',
  });
  const reasonRule = () => ({
    required: t('stillingar:cancelContract.missingId') ?? '',
  });

  const reasonDescriptionRule = (value: string | undefined | null) => {
    if (watchAllFields.reason.includes('Önnur') && !value) {
      return t('stillingar:cancelContract.missingRequiredReason');
    }
    return true;
  };

  return (
    <>
      <Box>
        <Text variant="pMediumBold">{t('stillingar:cancelContract.subtitle')}</Text>
        <Text variant="pMediumRegular">{t('stillingar:cancelContract.modalDescription')}</Text>
        {isTengir && (
          <Box marginTop={3}>
            <Text color="warning" variant="pMediumBold">
              {t('stillingar:confirmDeleteModal.cancelContract.isTengir')}
            </Text>
          </Box>
        )}
        <Box
          renderAs="form"
          onSubmit={handleSubmit(onSubmit)}
          display="flex"
          flexDirection="column"
          width="100%"
          marginTop={[3, 5]}
        >
          <Box marginBottom={5}>
            <Text variant="pMediumBold">{t('stillingar:cancelContract.modaldateTitle')}</Text>
            <Controller
              name="whenToApplyDate"
              control={control}
              render={() => {
                return (
                  <>
                    <Box display="flex" marginY={2} gap={4}>
                      <Datepicker
                        inputId="datepicker"
                        inputName="datepicker"
                        color="black100"
                        selected={watchAllFields.whenToApplyDate}
                        minDate={new Date()}
                        onSelect={(date: Date) => setValue('whenToApplyDate', date)}
                      />
                    </Box>
                  </>
                );
              }}
            />
          </Box>
          <Box marginBottom={5}>
            <Box display="flex" flexDirection="column">
              <Controller
                name="moveServiceTo"
                control={control}
                rules={moveServiceRule()}
                render={({ field, formState: { errors } }) => {
                  const { value } = field;
                  const findValue = autoCompleteMoveServiceToOptions?.find(
                    (option) => option.value === value,
                  );
                  return (
                    <>
                      <AutoComplete
                        options={
                          autoCompleteMoveServiceToOptions ?? [
                            { value: 'onnur-astaeda', label: 'Önnur ástæða' },
                          ]
                        }
                        label={t('stillingar:cancelContract.modalMoveTo')}
                        id="moveServiceCancel"
                        placeholder={t(
                          'stillingar:cancelContract.modalMoveToAutoCompletePlaceholder',
                        )}
                        onChange={(option) =>
                          option?.value && setValue('moveServiceTo', option.label)
                        }
                        value={findValue}
                        instanceId="moveServiceCancel"
                        closeMenuOnSelect
                        renderAs="select"
                        isSearchable={false}
                        isClearable={false}
                      />
                      <ErrorMessage
                        errors={errors}
                        name={field.name}
                        render={({ message }) => (
                          <FormStatusMessage message={message} status="error" />
                        )}
                      />
                    </>
                  );
                }}
              />
            </Box>
          </Box>
          <Box marginBottom={5}>
            <Box display="flex" flexDirection="column">
              <Controller
                name="reason"
                control={control}
                rules={reasonRule()}
                render={({ field, formState: { errors } }) => {
                  const { value } = field;
                  const findValue = autoCompleteReasonOptions?.find(
                    (autoCompleteReasonOption) => autoCompleteReasonOption.label === value,
                  );
                  return (
                    <>
                      <AutoComplete
                        options={
                          autoCompleteReasonOptions ?? [
                            { value: 'onnur-astaeda', label: 'Önnur ástæða' },
                          ]
                        }
                        label={t('stillingar:cancelContract.modalReason')}
                        id="reasonForCancel"
                        placeholder={t('stillingar:cancelContract.modalAutocompletePlaceholder')}
                        onChange={(option) => option?.value && setValue('reason', option.value)}
                        value={findValue}
                        instanceId="reasonForCancel"
                        closeMenuOnSelect
                        renderAs="select"
                        isSearchable={false}
                        isClearable={false}
                        isDisabled={!watchAllFields.moveServiceTo}
                      />
                      <ErrorMessage
                        errors={errors}
                        name={field.name}
                        render={({ message }) => (
                          <FormStatusMessage message={message} status="error" />
                        )}
                      />
                    </>
                  );
                }}
              />
            </Box>
          </Box>
          <Box>
            <Controller
              name="reasonDescription"
              control={control}
              rules={{
                minLength: {
                  value: 5,
                  message: t('stillingar:cancelContract.reasonMinLength'),
                },
                validate: reasonDescriptionRule,
              }}
              render={({ field, formState: { errors } }) => {
                const { value, ...rest } = field;

                return (
                  <>
                    <Input
                      type="text"
                      id="messageBox"
                      label={t('stillingar:cancelContract.modalOtherReasonPlaceholder')}
                      value={value ?? ''}
                      {...rest}
                    />
                    <ErrorMessage
                      errors={errors}
                      name={field.name}
                      render={({ message }) => (
                        <FormStatusMessage message={message} status="error" />
                      )}
                    />
                  </>
                );
              }}
            />
          </Box>
          {isStaff && (
            <Box marginY={8} display="flex" flexDirection="row" alignItems="center" gap={2}>
              <Icon icon="warning" size={32} />
              <Box gap={2} display="flex" flexDirection="column">
                <Text variant="pSmallBold">
                  {t('stillingar:cancelContract.staffCustomerAlltSaman')}
                </Text>
                <Text variant="pSmallBold">
                  {t('stillingar:cancelContract.staffCustomerMoveService')}
                </Text>
                <Text variant="pSmallBold">
                  {t('stillingar:cancelContract.staffCustomerEquipment')}
                </Text>
              </Box>
            </Box>
          )}
          <SettingsButtons
            cancelButton={{
              text: t('stillingar:cancelContract.modalCancelButton'),
              colorScheme: 'white',
              dottedShadow: 'none',
              onClick: () => {
                setValue('reason', '');
                reset();
              },
            }}
            confirmButton={{
              text: t('stillingar:cancelContract.modalSubmitButton'),
              colorScheme: ui?.serviceColor ?? 'pink',
              dottedShadow: 'none',
              isDisabled: !formState.isValid,
              isLoading: formState.isSubmitting,
              isSubmitButton: true,
              icon: 'longArrowRight',
            }}
          />
        </Box>
      </Box>
      <ConfirmDeleteModal
        isVisible={showConfirmationModal}
        whenToApplyDate={watchAllFields.whenToApplyDate}
        onVisibilityChange={(isVisible: boolean) => setShowConfirmationModal(isVisible)}
        onClose={() => {
          setShowConfirmationModal(false);
        }}
        onDelete={() => handleCancelContract()}
      />
    </>
  );
};

export default inject('ui', 'authentication')(observer(CancelContractContainer));
